import {assert} from "../utils/assert";

let _head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;

const ScriptRender = {
    /**
     * 添加外部的URL引用
     * @param url 外部URL地址
     * @attrs 额外附加在style标签上的属性
     */
    addStyle: function (url = undefined, attrs = undefined) {
        assert(url === undefined, "style url is undefined");
        let element = document.createElement('link');
        element.setAttribute('rel', 'stylesheet');
        element.setAttribute('type', 'text/css');
        element.setAttribute('href', url);
        if (attrs !== undefined) {
            for (let key in attrs) {
                script.setAttribute(key, attr[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    /**
     * 添加外部Javascript引用
     * @param url 外部JS地址
     * @attrs 额外附加在script标签上的属性
     */
    addJavascript: function (url, attrs = undefined) {
        assert(url === undefined, "script url is undefined");
        let deferred = $.Deferred(), script = document.createElement("script");
        script.type = 'text/javascript';
        script.charset = 'utf-8';
        script.async = true;
        script.src = url;
        if (attrs !== undefined) {
            for (let key in attrs) {
                script.setAttribute(key, attr[key]);
            }
        }
        script.onerror = () => {
            console.error("javascript load failure!, URL=" + url);
            deferred.reject();
        };
        script.onload = script.onreadystatechange = (_, isAbort) => {
            if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
                script.onload = script.onreadystatechange = null;
                script = null;
                if (!isAbort) {
                    deferred.resolve();
                } else {
                    deferred.reject();
                    console.error("load javascript abort!, URL=" + url);
                }
            }
        };
        _head.appendChild(script);
        return deferred.promise();
    },
    addEmbedStyle: function (code, attrs = undefined) {
        let element = document.createElement("style");
        if (element.styleSheet) {
            element.styleSheet.cssText = code;
        } else {
            element.innerHTML = code;
        }
        if (attrs !== undefined) {
            for (let key in attrs) {
                element.setAttribute(key, attrs[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    addEmbedScript: function (code, attrs = undefined) {
        let element = document.createElement("script");
        element.setAttribute("language", "Javascript");
        element.text = code;
        if (attrs !== undefined) {
            for (let key in attrs) {
                element.setAttribute(key, attrs[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    /**
     * 检查外部样式是否引用
     * @param predicate 移除样式的依据, 可以是URL或函数
     * @returns {boolean} 引用情况
     */
    checkStyle: function (predicate) {
        let exists = false;
        if (typeof predicate === 'string') {
            $.each(document.head.childNodes, (index, item) => {
                if (item.nodeName === 'LINK' && item.attributes['href'].value === predicate) {
                    exists = true;
                    return false;
                }
            });
        } else if (typeof  predicate === 'function') {
            $.each(document.head.childNodes, (index, item) => {
                if ((item.nodeName === 'LINK' || item.nodeName === 'STYLE') && predicate.call(undefined, item)) {
                    exists = true;
                    return false;
                }
            });
        }
        return exists;
    },
    /**
     * 移除外接样式
     * @param predicate 移除样式的依据, 可以是URL或函数
     */
    removeStyle: function (predicate) {
        if (typeof predicate === 'string') {
            let url = predicate;
            document.head.childNodes.forEach(item => {
                if (item.nodeName === 'LINK' && item.attributes['href'].value === url) {
                    _head.removeChild(item);
                }
            });
        } else if (typeof predicate === 'function') {
            document.head.childNodes.forEach(item => {
                if (item.nodeName === 'LINK' && predicate.call(undefined, item)) {
                    _head.removeChild(item);
                }
            });
        }
    },
    removeStyleElement: function (element = undefined) {
        assert(element === undefined, "style element is undefined");
        _head.removeChild(element);
        element = null;
    }
};

export {ScriptRender};